package com.gujiangbo.threadpool;

import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.stream.IntStream;

/**
 * @Author: gujiangbo.co
 * @Contact: 646832012@qq.com
 * @Date: 2022/3/11 10:46
 * @Version: 1.0
 * @Description: 1.在创建了线程池后，等待提交过来的任务请求。
 * 2.当调用execute()方法添加一个请求任务时，线程池会做如下判断:
 * 2.1 如果正在运行的线程数量小于corePoolSize，那么马上创建线程运行这个任务;
 * 2.2如果正在运行的线程数量大于或等于corePoolSize，那么将这个任务放入队列:
 * 2.3如果这时候队列满了且正在运行的线程数量还小于maximumPoolSize，那么还是要创建非核心线程立刻运行这个任务。
 * 2.4如果队列满了且正在运行的线程数量大于或等于maximumPoolSize，那么线程池会启动饱和拒绝策略来执行。
 * 3.当一个线程完成任务时，它会从队列中取下一个任务来执行。
 * 4.当一个线程无事可做超过一定的时间(keepAliveTime)时，线程池会判断:
 * 如果当前运行的线程数大于corePoolSize，那么这个线程就被停掉。
 */
public class T1 {

    /**
     * 模拟线程池的运行，以银行排队办业务为例
     *
     * @param args
     */
    public static void main(String[] args) {
        ThreadPoolExecutor threadPool = new ThreadPoolExecutor(
                2,// 核心下线程数--对外开放的两个VIP窗口
                5,//最大核心线程数 --最多能开放的窗口(包括VIP窗口、普通业务窗口)
                100L,//多余空闲线程的存活时间百度
                TimeUnit.SECONDS,// 多余空闲线程的搓火时间单位
                new LinkedBlockingQueue<>(3),//等候区最大的座位
                new ThreadPoolExecutor.AbortPolicy()// 超出窗口运营能力会抛出异常
        );

        try {
            // 模拟6人办理业务，受理的最大窗口只有5个。
            IntStream.range(1, 7).forEach(v -> threadPool.execute(() -> {
                System.out.println(Thread.currentThread().getName() + "号窗口，" + "服务顾客" + v);
                try {
                    TimeUnit.SECONDS.sleep(4);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }));
        } catch (Exception ignored) {
        } finally {
            threadPool.shutdown();
        }
    }
}
